export const CommandExecute = {
    undo: () => { },
    redo: () => { },
}

export const Command = {
    name: '',                               // 命令唯一标识
    keyboard: '',                           // 命令监听的快捷键
    execute: (...args) => CommandExecute,   // 命令被执行的时候，所做的内容
    followQueue: false,                     // 命令执行完之后，是否要将命令执行得到的undo,redo存入命令队列
    data: {},                               //命令缓存数据
    init: () => { },                        //命令初始化函数
    destroy: () => { },                     //命令初始化函数

}

export const CommandManager = {
    queue: [CommandExecute], // 队列数组
    current: 0, // 队列索引
}

// 把状态存在全局上，防止每次执行 createCommander 重置
const state = {
    current: -1, // 队列中当前的命令 
    commands: {},// 命令对象，方便通过命令的名称调用命令的execute函数
    queue: [], // 命令队列
    commandArray: [],// 命令对象数组
    destoryList: [], // 组件销毁的时候，需要调用的
}

export function createCommander() {
    // const state = {
    //     current: -1,
    //     commands: {},
    //     queue: [],
    // }
    // console.log('registry state', state);

    // 注册命令
    const registry = (command) => {
        // console.log('registry command', command); 

        state.commandArray.push(command);

        state.commands[command.name] = (...args) => {
            const { undo, redo } = command.execute(...args)
            redo()
            // !!command.init && command.init()
            // 如果命令执行之后，不需要进入命令队列，则直接结束
            if (command.followQueue === false) {
                return
            }
            // 否则，将命令队列中剩余的命令去除
            let { queue, current } = state;
            if (queue.length > 0) {
                queue = queue.slice(0, current + 1);
                state.queue = queue;
            }
            queue.push({ undo, redo })
            state.current = current + 1
        }
    }

    const init = () => {
        const onKeydown = (e) => {
            // console.log('监听到键盘事件');
        }
        window.addEventListener('keydown', onKeydown);
        state.commandArray.forEach(command => !!command.init && state.destoryList.push(command.init()))
        state.destoryList.push(() => window.removeEventListener('keydown', onKeydown))
    };
    const destroy = () => { };

    // 注册撤回命令
    registry({
        name: 'undo',
        keyboard: 'ctrl+z',
        followQueue: false,
        execute: () => {
            // 命令被执行时要做的事情
            return {
                redo: () => {
                    console.log('执行撤销', state);
                    // 重新做一遍，要做的事情
                    if (state.current === -1) return
                    const queueItem = state.queue[state.current];
                    if (!!queueItem) {
                        !!queueItem.undo && queueItem.undo();
                        state.current--
                    }
                },
                undo: () => {
                    // 将做的事情还原
                },
            }
        }
    })

    registry({
        name: 'redo',
        keyboard: [
            'ctrl+y',
            'ctrl+shift+z',
        ],
        followQueue: false,
        execute: () => {
            // 命令被执行时要做的事情
            return {
                redo: () => {
                    console.log('执行重做', state);
                    // 重新做一遍，要做的事情
                    const queueItem = state.queue[state.current + 1];
                    if (!!queueItem) {
                        queueItem.redo()
                        state.current++
                    }
                },
                undo: () => {
                    // 将做的事情还原
                },
            }
        }
    })

    // onUnmounted(() => {
    // state.destoryList.forEach(fn => !!fn() && fn())
    // })

    return {
        state,
        registry,
        init,
    }
}
